//
//Pattern
//
//This class essentially acts as a shell to add functions to a vector of arrays
//meant to store word vectors from a corpus. These functions for the most part
//serve to check for errors and create a matrix from the pattern if necessary.
//Pattern had to have an underlying vector because the ability to append 
//words to the vector as the grammar was being generated was essential. An
//array of arrays couldn't allow for this since the exact number of rows
//(total words) is semi-stochastic and unknown before the sentences are
//generated. It should also be noted that the add function subtracts 0.5 from
//each element before adding it to the set. This has to do with the specific
//properties of echo state networks and can be disabled if other values are
//desired.
//
//Zach Tosi Feb 9 2011
//Special Thanks to the creators of the JAMA matrix package.
package utils.corpus_generator;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Vector;

import Jama.Matrix;

public class Pattern {

	private Vector<double []> Pat;
	private Vector<int []> Verb;
	private int length;
	public boolean replace = false;
	public int [] Inds;
	
	//Default Constructor
	public Pattern(){
		Pat = new Vector<double[]>();
		Verb = null;
	}
	
	//Constructor takes in the length for each array that will be stored in
	//vector Pat. 
	public Pattern(int length){
		Pat = new Vector<double []>();
		Verb = null;
		this.length = length;
	}
	
	public void MakeVerbInds(){
		Verb = new Vector<int []>();
	}
	
	public void AddNounInd(){
		Inds = new int[2];
		Inds[1] = getRowDim();
		Inds[0] = 0;
	}
	
	public void AddVerb(){
		Inds[0] = getRowDim();
		Inds[1] = Inds[0] - Inds[1];
		Verb.add(Inds);
	}
	
	//Add function overrides the vector add function in order to catch errors
	//in length consistency, since all arrays added should have the same length
	public void Add(double [] token){
		
		if(token.length != length){
			throw new IllegalArgumentException("Length inconsistency");
		}
		
		
		Pat.add(token);
	}
	
	//Uses the Jama matrix package to convert the set of sentences into
	//a matrix. This allows us to use the Jama Matrix print function to print
	//out the sentences to a file.
	public Matrix createMatrix(){
		Matrix tSet = new Matrix(Get2DArray());
		return tSet;
	}
	public void Print(String Filename){
		try{
		File Output = new File(Filename);
		FileOutputStream FOS = new FileOutputStream(Output);
		PrintWriter Mat = new PrintWriter(FOS); 
		Matrix TrSet = createMatrix();
		TrSet.print(Mat, 2, 2);

		Mat.close();
		}catch(IOException e){
			System.err.println(e);
		}
	}
		
	public void Translate(String Filename){
		try{
		@SuppressWarnings("unused")
		int periods = 0;
		File trans = new File(Filename);
		FileOutputStream Fos = new FileOutputStream(trans);
		OutputStreamWriter OOS = new OutputStreamWriter(Fos);
		PrintWriter translation = new PrintWriter(OOS);

		
		for(int j = 0; j < getRowDim(); j ++){
			for(int i = 0; i < getLength(); i++){
				if(get(j, i) == 1.0){
					int ind = i;
					switch(ind){
					case 0: translation.write("boy "); break;
					case 1: translation.write("girl "); break;
					case 2: translation.write("cat "); break;
					case 3: translation.write("dog "); break;
					case 4: translation.write("John "); break;
					case 5: translation.write("Mary "); break;
					case 6: translation.write("boys "); break;
					case 7: translation.write("girls "); break;
					case 8: translation.write("cats "); break;
					case 9: translation.write("dogs "); break;
					case 10: translation.write("chase "); break;
					case 11: translation.write("feed "); break;
					case 12: translation.write("see "); break;
					case 13: translation.write("hear "); break;
					case 14: translation.write("walk "); break;
					case 15: translation.write("live "); break;
					case 16: translation.write("chases "); break;
					case 17: translation.write("feeds "); break;
					case 18: translation.write("sees "); break;
					case 19: translation.write("hears "); break;
					case 20: translation.write("lives "); break;
					case 21: translation.write("walks "); break;
					case 22: translation.write("who "); break;
					case 23: {translation.write(". \n"); 
								periods++; }			break;
					
					//case 24: {translation.write(". \n");
							// periods++;} 				break;
					default: translation.write("Error "); break; 
				}
				}
			}
		}
	
	
	translation.close();

	
	System.out.println("words/sentence: " + (double)
			(getRowDim()));
		}catch(IOException e){
			System.err.println(e);
		}
	}
	
	//Standard Accessors
	public double get(int m, int n){
		return Pat.get(m)[n];
	}
	
	public int getRowDim(){
		return Pat.size();
	}
	
	public int getLength(){
		return length;
	}
	
	public void setLength(int L){
		length = L;
	}
	
	public void Set2dVec(Vector<double []> P){
		Pat = P;
	}
	
	public Vector<double []> get2dVec(){
		return Pat;
	}
	
	public void Clear(){
		Pat.removeAllElements();
	}
	
	public double [] GetLast(){
		return Pat.lastElement();
	}
	
	public int IndexOfLast(){
		return Pat.size()-1;
	}
	
	public Vector<int []> GetVerbs(){
		return Verb;
	}
	
	public void SetLast(double [] P){
		RemoveBottom();
		Pat.add(P);
	}
	
	public void RemoveBottom(){
		Pat.remove(Pat.lastElement());
	}
	
	public double [][] Get2DArray(){
		double [][] Set = new double[getRowDim()][length];
		for(int i = 0; i < Pat.size(); i++){
			for(int j = 0; j < length; j++){
				double Val = Pat.get(i)[j];
				Set[i][j] = Val;
			}
		}
		return Set;
	}
}
